package cn.com.chengmandian.bike.utils;

import cn.com.chengmandian.bike.model.EbPriceRule;
import cn.com.chengmandian.bike.model.EbPriceStep;
import cn.com.chengmandian.bike.model.vo.MemberCardVo;
import cn.com.chengmandian.bike.model.vo.RideOrderCountVo;
import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.service.bike.constants.CardInfoCouponTypeEnum;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

@Slf4j
public class OrderPriceUtil {

    // 时长收费
    public static BigDecimal getTimeMoney(RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule, MemberCardVo memberCard) {
        // 剩余需计费时长
        Integer countRideTime = rideOrderCountVo.getAllTime() - rideOrderCountVo.getNewFreeTime();
        if (countRideTime < 0) countRideTime = 0;
        // 有减免时间的骑行卡
        if (memberCard != null && memberCard.getCouponType().equals(CardInfoCouponTypeEnum.TIME.getCode()) && memberCard.getCouponTime() != null) {
            rideOrderCountVo.setCardRecordId(memberCard.getId());
            rideOrderCountVo.setCardFreeTime(memberCard.getCouponTime());
            countRideTime = rideOrderCountVo.getAllTime() - memberCard.getCouponTime();
            if (countRideTime < 0) countRideTime = 0;
        }
        rideOrderCountVo.setRideTime(countRideTime);

        // 骑行费用
        BigDecimal timeMoney = getBasicRideMoney(countRideTime, rideOrderCountVo, priceRule);

        // 有限价策略 封顶费用限制
        timeMoney = getCappingMoney(countRideTime, timeMoney, rideOrderCountVo, priceRule, null);
        return timeMoney;
    }

    // 时长阶梯计费
    public static BigDecimal getTimeMoney(RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule, List<EbPriceStep> priceSteps, MemberCardVo memberCard) {
        // 剩余需计费时长
        Integer countRideTime = rideOrderCountVo.getAllTime() - rideOrderCountVo.getNewFreeTime();
        if (countRideTime < 0) countRideTime = 0;
        // 有减免时间的骑行卡
        if (memberCard != null && memberCard.getCouponType().equals(CardInfoCouponTypeEnum.TIME.getCode()) && memberCard.getCouponTime() != null) {
            countRideTime = rideOrderCountVo.getAllTime() - memberCard.getCouponTime();
            if (countRideTime < 0) countRideTime = 0;

            rideOrderCountVo.setCardRecordId(memberCard.getId());
            rideOrderCountVo.setCardFreeTime(memberCard.getCouponTime());
        }
        rideOrderCountVo.setRideTime(countRideTime);
        if(countRideTime <= CommonConstant.ZERO) return BigDecimal.ZERO;

        // 骑行卡减免之后用户骑行总时长
        Integer calculateRideTime = CommonConstant.ZERO + countRideTime;

        // 基础时长费用
        BigDecimal timeMoney = getBasicPriceStepsRideMoney(countRideTime, rideOrderCountVo, priceRule, priceSteps);

        // 有限价策略 封顶费用限制
        timeMoney = getCappingMoney(calculateRideTime, timeMoney, rideOrderCountVo, priceRule, priceSteps);
        return timeMoney;
    }

    // 封顶计算
    private static BigDecimal getCappingMoney(Integer countRideTime, BigDecimal timeMoney, RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule, List<EbPriceStep> priceSteps) {
        // 如果有限价策略
        if (priceRule.getCappingMinute() != null && priceRule.getCappingMinute() > 0) {
            // 并且设置了费用上限
            if (priceRule.getCappingMinuteFee() != null && priceRule.getCappingMinuteFee().compareTo(BigDecimal.ZERO) > 0) {
                // 骑行金额超过封顶金额(时间不超 金额超)
                if(countRideTime < priceRule.getCappingMinute() && timeMoney.compareTo(priceRule.getCappingMinuteFee()) > 0){
                    timeMoney = priceRule.getCappingMinuteFee();
                    rideOrderCountVo.setCappingTimeMoney(timeMoney);

                }else {
                    // 骑行时长超过封顶时长 封顶金额相对乘以骑行时长和封顶时长的倍数 金额超过计算之后的封顶金额
                    Integer topMoneyNumbers = countRideTime / priceRule.getCappingMinute();
                    if(topMoneyNumbers == null || topMoneyNumbers <= 0) topMoneyNumbers = 0;
                    if (countRideTime >= priceRule.getCappingMinute() && timeMoney.compareTo(priceRule.getCappingMinuteFee().multiply(BigDecimal.valueOf(topMoneyNumbers))) > 0) {
                        Integer overTopMoneyTime = countRideTime % priceRule.getCappingMinute();
                        BigDecimal topRideMoney = BigDecimal.ZERO;
                        if (topMoneyNumbers > 0) {
                            topRideMoney = NumberUtil.mul(priceRule.getCappingMinuteFee(), topMoneyNumbers);
                            timeMoney = topRideMoney;
                            rideOrderCountVo.setCappingTime(topMoneyNumbers * priceRule.getCappingMinute());
                            rideOrderCountVo.setCappingTimeMoney(topRideMoney);
                        }

                        // 超出时间按基本费用配置来算
                        if (overTopMoneyTime > 0) {
                            if(priceSteps == null || priceSteps.size() <= 0) {
                                BigDecimal overTopMoney = getBasicRideMoney(overTopMoneyTime, rideOrderCountVo, priceRule);
                                if (overTopMoney.compareTo(priceRule.getCappingMinuteFee()) > 0) {
                                    overTopMoney = priceRule.getCappingMinuteFee();
                                    rideOrderCountVo.setCappingTimeMoney(topRideMoney.add(overTopMoney));
                                }
                                timeMoney = timeMoney.add(overTopMoney);
                            } else {
                                BigDecimal overTopMoney = getBasicPriceStepsRideMoney(overTopMoneyTime, rideOrderCountVo, priceRule, priceSteps);
                                if (overTopMoney.compareTo(priceRule.getCappingMinuteFee()) > 0) {
                                    overTopMoney = priceRule.getCappingMinuteFee();
                                    rideOrderCountVo.setCappingTimeMoney(topRideMoney.add(overTopMoney));
                                }
                                timeMoney = timeMoney.add(overTopMoney);
                            }
                        }
                    }
                }
            }
        }
        return timeMoney;
    }

    /**
     * 非阶梯价基础骑行费用
     */
    private static BigDecimal getBasicRideMoney(Integer countRideTime, RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule) {
        if(countRideTime <= 0) return BigDecimal.ZERO;
        rideOrderCountVo.setBeforeTime(CommonConstant.ZERO);
        rideOrderCountVo.setBeforeTimeMoney(BigDecimal.ZERO);
        rideOrderCountVo.setOverTime(CommonConstant.ZERO);
        rideOrderCountVo.setOverRideTimeMoney(BigDecimal.ZERO);

        rideOrderCountVo.setBeforeTime(priceRule.getBeforeMinute()); // 起步时长
        // 如果有起步价
        if (priceRule.getBeforeMinuteFee().compareTo(BigDecimal.ZERO) > 0) {
            rideOrderCountVo.setBeforeTimeMoney(priceRule.getBeforeMinuteFee()); // 起步时长价格
        }
        if (countRideTime > priceRule.getBeforeMinute()) {
            rideOrderCountVo.setOverTime(countRideTime - priceRule.getBeforeMinute());
            // 如果超时时长大于0，计算超时费用
            if (priceRule.getAfterMinuteFee().compareTo(BigDecimal.ZERO) > 0 && priceRule.getAfterMinute() > 0) {
                rideOrderCountVo.setOverRideTimeMoney(NumberUtil.mul(priceRule.getAfterMinuteFee(), NumberUtil.div(rideOrderCountVo.getOverTime(), priceRule.getAfterMinute(), 0, RoundingMode.UP)));
            }
        }
        BigDecimal timeMoney = rideOrderCountVo.getBeforeTimeMoney().add(rideOrderCountVo.getOverRideTimeMoney());
        return timeMoney;
    }

    /**
     * 阶梯价基础骑行费用
     */
    private static BigDecimal getBasicPriceStepsRideMoney(Integer countRideTime, RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule, List<EbPriceStep> priceSteps) {
        if(countRideTime <= 0) return BigDecimal.ZERO;
        rideOrderCountVo.setBeforeTime(CommonConstant.ZERO);
        rideOrderCountVo.setBeforeTimeMoney(BigDecimal.ZERO);
        rideOrderCountVo.setOverTime(CommonConstant.ZERO);
        rideOrderCountVo.setOverRideTimeMoney(BigDecimal.ZERO);

        // 前x分钟计费
        Integer beforeRideTime = priceRule.getBeforeMinute();
        BigDecimal beforeRideTimeMoney = priceRule.getBeforeMinuteFee();
        countRideTime = countRideTime - beforeRideTime;
        if(countRideTime > CommonConstant.ZERO) {
            // 阶梯计价
            for (EbPriceStep priceStep : priceSteps) {
                countRideTime = countRideTime - priceStep.getMinutePart();
                beforeRideTime = beforeRideTime + priceStep.getMinutePart();
                beforeRideTimeMoney = beforeRideTimeMoney.add(priceStep.getMinuteFee());
                if (countRideTime <= 0) break;
            }
        }
        rideOrderCountVo.setBeforeTime(beforeRideTime);
        rideOrderCountVo.setBeforeTimeMoney(beforeRideTimeMoney);

        if (countRideTime > CommonConstant.ZERO) {
            rideOrderCountVo.setOverTime(countRideTime);
            // 如果超时时长大于0，计算超时费用
            if (priceRule.getAfterMinuteFee().compareTo(BigDecimal.ZERO) > 0 && priceRule.getAfterMinute() > 0) {
                rideOrderCountVo.setOverRideTimeMoney(NumberUtil.mul(priceRule.getAfterMinuteFee(), NumberUtil.div(rideOrderCountVo.getOverTime(), priceRule.getAfterMinute(), 0, RoundingMode.UP)));
            }
        }
        // 基础时长费用
        BigDecimal timeMoney = rideOrderCountVo.getBeforeTimeMoney().add(rideOrderCountVo.getOverRideTimeMoney());
        return timeMoney;
    }

    public static BigDecimal getBasicRideMoney(Integer countRideTime, EbPriceRule priceRule) {
        // 如果有起步价
        BigDecimal beforeTimeMoney = BigDecimal.ZERO;
        if (priceRule.getBeforeMinuteFee().compareTo(BigDecimal.ZERO) > 0) {
            beforeTimeMoney = priceRule.getBeforeMinuteFee(); // 起步时长价格
        }

        // 超时费用
        BigDecimal overRideTimeMoney = BigDecimal.ZERO;
        if (countRideTime > priceRule.getBeforeMinute()) {
            // 超时时长
            Integer overTime = countRideTime - priceRule.getBeforeMinute();
            // 如果超时时长大于0，计算超时费用
            if (priceRule.getAfterMinuteFee().compareTo(BigDecimal.ZERO) > 0 && priceRule.getAfterMinute() > 0) {
                overRideTimeMoney = NumberUtil.mul(priceRule.getAfterMinuteFee(), NumberUtil.div(overTime, priceRule.getAfterMinute(), 0, RoundingMode.UP));
            }
        }
        BigDecimal timeMoney = beforeTimeMoney.add(overRideTimeMoney);
        return timeMoney;
    }

    public static BigDecimal getBasicRideMoney(Integer orderFreeAfterTime, EbPriceRule priceRule, List<EbPriceStep> priceSteps) {
        BigDecimal beforeRideTimeMoney = priceRule.getBeforeMinuteFee();
        for(EbPriceStep priceStep : priceSteps) {
            beforeRideTimeMoney = beforeRideTimeMoney.add(priceStep.getMinuteFee());
            orderFreeAfterTime = orderFreeAfterTime - priceStep.getMinutePart();
            if(orderFreeAfterTime <= 0) break;
        }

        // 超时费用
        BigDecimal overRideTimeMoney = BigDecimal.ZERO;
        if (orderFreeAfterTime > priceRule.getBeforeMinute()) {

            // 如果超时时长大于0，计算超时费用
            if (priceRule.getAfterMinuteFee().compareTo(BigDecimal.ZERO) > 0 && priceRule.getAfterMinute() > 0) {
                overRideTimeMoney = NumberUtil.mul(priceRule.getAfterMinuteFee(), NumberUtil.div(orderFreeAfterTime, priceRule.getAfterMinute(), 0, RoundingMode.UP));
            }
        }
        BigDecimal timeMoney = beforeRideTimeMoney.add(overRideTimeMoney);
        return timeMoney;
    }

    // 距离收费
    public static BigDecimal getDistanceMoney(RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule) {
        Integer countRideDistance = new BigDecimal(rideOrderCountVo.getAllDistance()).divide(new BigDecimal(1000),0,BigDecimal.ROUND_HALF_UP).intValue();;
        rideOrderCountVo.setRideDistance(countRideDistance);

        // 基础距离收费
        BigDecimal distanceMoney = getBasicDistanceMoney(countRideDistance, rideOrderCountVo, priceRule);
        if(distanceMoney.compareTo(BigDecimal.ZERO) <= 0) return distanceMoney; // 金额是0，直接跳出

        // 如果有限价策略
        if (priceRule.getCappingDistance() != null && priceRule.getCappingDistance() > 0) {
            if (priceRule.getCappingDistanceFee() != null && priceRule.getCappingDistanceFee().compareTo(BigDecimal.ZERO) > 0) {
                // 骑行距离没有超出 骑行距离费用超过封顶
                if(countRideDistance < priceRule.getCappingDistance() && distanceMoney.compareTo(priceRule.getCappingDistanceFee()) > 0) {
                    distanceMoney = priceRule.getCappingDistanceFee();
                    rideOrderCountVo.setCappingDistanceMoney(distanceMoney);
                }else {
                    // 骑行时长超过封顶距离 封顶金额相对乘以骑行距离和封顶距离的倍数 金额超过计算之后的封顶金额
                    Integer topMoneyNumbers = countRideDistance / priceRule.getCappingDistance();
                    if(topMoneyNumbers == null || topMoneyNumbers <= 0) topMoneyNumbers = 0;
                    if (countRideDistance >= priceRule.getCappingDistance() && distanceMoney.compareTo(priceRule.getCappingDistanceFee().multiply(BigDecimal.valueOf(topMoneyNumbers))) > 0) {
                        Integer topDistanceNumbers = countRideDistance / priceRule.getCappingDistance();
                        Integer overTopRideDistance = countRideDistance % priceRule.getCappingDistance();
                        BigDecimal topDistanceMoney = BigDecimal.ZERO;
                        if (topDistanceNumbers > 0) {
                            topDistanceMoney = NumberUtil.mul(priceRule.getCappingDistanceFee(), topDistanceNumbers);
                            distanceMoney = topDistanceMoney;
                            rideOrderCountVo.setCappingDistanceMoney(topDistanceMoney);
                            rideOrderCountVo.setCappingDistance(topDistanceNumbers * priceRule.getCappingDistance());
                        }

                        // 超出距离按基本费用配置来算
                        if (overTopRideDistance > 0) {
                            BigDecimal overTopRideDistanceMoney = getBasicDistanceMoney(overTopRideDistance, rideOrderCountVo, priceRule);
                            if (overTopRideDistanceMoney.compareTo(priceRule.getCappingDistanceFee()) > 0) {
                                overTopRideDistanceMoney = priceRule.getCappingDistanceFee();
                                rideOrderCountVo.setCappingDistanceMoney(topDistanceMoney.add(overTopRideDistanceMoney));
                            }
                            distanceMoney = distanceMoney.add(overTopRideDistanceMoney);
                        }
                    }
                }
            }
        }
        return distanceMoney;
    }

    public static BigDecimal getBasicDistanceMoney(Integer countRideDistance, RideOrderCountVo rideOrderCountVo, EbPriceRule priceRule) {
        if (countRideDistance <= 0) return BigDecimal.ZERO;
        rideOrderCountVo.setBeforeDistance(CommonConstant.ZERO);
        rideOrderCountVo.setBeforeDistanceMoney(BigDecimal.ZERO);
        rideOrderCountVo.setOverDistance(CommonConstant.ZERO);
        rideOrderCountVo.setOverDistanceMoney(BigDecimal.ZERO);

        rideOrderCountVo.setBeforeDistance(priceRule.getBeforeDistance());
        if (priceRule.getBeforeDistanceFee().compareTo(BigDecimal.ZERO) > 0) {
            rideOrderCountVo.setBeforeDistanceMoney(priceRule.getBeforeDistanceFee());
        }
        if (countRideDistance > priceRule.getBeforeDistance()) {
            rideOrderCountVo.setOverDistance(countRideDistance - priceRule.getBeforeDistance());
            if (priceRule.getAfterDistanceFee().compareTo(BigDecimal.ZERO) > 0 && priceRule.getAfterDistance() > 0) {
                rideOrderCountVo.setOverDistanceMoney(NumberUtil.mul(priceRule.getAfterDistanceFee(), NumberUtil.div(rideOrderCountVo.getOverDistance(), priceRule.getAfterDistance(), 0, RoundingMode.UP)));
            }
        }
        BigDecimal distanceMoney = rideOrderCountVo.getBeforeDistanceMoney().add(rideOrderCountVo.getOverDistanceMoney());
        return distanceMoney;
    }
}
